﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;

namespace memo
{
    /// <summary>
    /// Szöveges tartalom és hozzá tartozó média állományok.
    /// </summary>
    [Serializable]
    public class Content
    {

        /// <summary>
        /// Content tudását meghatározó enum.
        /// </summary>
        public enum KnowledgeStatus { EMPTY = 0, HALF = 50, FULL = 100 };

        #region Class getter and setter.
        /// <summary>
        /// A content címe. Nem lehet null.
        /// </summary>
        public string Title
        {
            get
            {
                return myTitle;
            }
            set
            {
                if (value != null)
                {
                    myTitle = value;
                }
            }
        }

        /// <summary>
        /// Visszaadja/beállítja a tartalom szövegét. Lehet null is.
        /// </summary>
        public string Details { get; set; }

        /// <summary>
        /// Visszaadja/beállítja a képek listáját. Lehet null is.
        /// </summary>
        public List<string> Pictures { get; set; }

        /// <summary>
        /// Visszaadja/beállítja az audió fájlok listáját. Lehet null is.
        /// </summary>
        public List<AudioFile> Audios { get; set; }

        /// <summary>
        /// Visszaadja/beállítja a videó fájlok listáját. Lehet null is.
        /// </summary>
        public List<VideoFile> Videos { get; set; }

        /// <summary>
        /// Visszaadja/beállítja az adott content tudásának státuszát. Nem lehet null.
        /// </summary>
        public KnowledgeStatus Status { get; set; }

        /// <summary>
        /// Visszaadja/beállítja a Content ikonját. Nem lehet null.
        /// </summary>
        /// <returns></returns>
        public Image Icon
        {
            get
            {
                return myIcon;
            }
            set
            {
                if (value != null)
                {
                    myIcon = value;
                }
                else
                {
                    myIcon = Properties.Resources.defaultIcon;
                }
            }
        }

        /// <summary>
        /// Visszaadja, hogy az adott Contentet mennyire tudja a felhasználó.
        /// </summary>
        /// <returns></returns>
        public double GetKnowledgePercent()
        {
            return (double)Status;
        }

        /// <summary>
        /// Nullára állítja a Content tudásszázalékát.
        /// </summary>
        public void ResetKnowledgePercent()
        {
            Status = KnowledgeStatus.EMPTY;
        }

        /// <summary>
        /// Százra állítja a Content tudásszázalékát.
        /// </summary>
        public void FullKnowledgePercent()
        {
            Status = KnowledgeStatus.FULL;
        }
        #endregion

        #region Definition of the class' constructors.
        /// <summary>
        /// Content inicializálása a cím megadásával.
        /// </summary>
        /// <param name="title">cím</param>
        public Content(string title)
            : this(title, null, null, null, null, null)
        { }

        public Content(string title, string detail)
            : this(title, detail, null, null, null, null)
        { }

        /// <summary>
        /// Konstruktor az osztály használatához.
        /// </summary>
        /// <param name="title">cím</param>
        /// <param name="details">leírás</param>
        /// <param name="pictures">Képek listája.</param>
        /// <param name="audios">Hangok listája.</param>
        /// <param name="videos">Videók listája.</param>
        /// <param name="iconFilePath">A Content ikonja.</param>
        public Content(string title, string details, List<string> pictures, List<AudioFile> audios, List<VideoFile> videos, Image icon)
        {
            if (string.IsNullOrWhiteSpace(title))
            {
                Title = "Untitled";
            }
            else
            {
                Title = title;
            }

            Details = details;
            Pictures = pictures;
            Audios = audios;
            Videos = videos;
            if (icon != null)
            {
                Icon = icon;
            }
            else
            {
                Icon = Properties.Resources.defaultIcon;
            }
            Status = KnowledgeStatus.EMPTY;
        }
        #endregion

        #region Add one item List type fields.
        /// <summary>
        /// Egy képfájl hozzáadása.
        /// </summary>
        /// <param name="image">Hozzáadni kívánt képfájl.</param>
        /// <returns>Igazat ad vissza ha a művelet sikeres volt.</returns>
        public bool AddImage(string image)
        {
            if (Pictures != null)
            {
                Pictures.Add(image);
                return true;
            }
            return false;
        }

        /// <summary>
        /// Egy hangfájl hozzáadása.
        /// </summary>
        /// <param name="audio">Hozzáadni kívánt hangfájl.</param>
        /// <returns>Igazat ad vissza ha a művelet sikeres volt.</returns>
        public bool AddAudio(AudioFile audio)
        {
            if (Audios != null)
            {
                Audios.Add(audio);
                return true;
            }
            return false;
        }

        /// <summary>
        /// Egy videófájl hozzáadása.
        /// </summary>
        /// <param name="video">Hozzáadni kívánt videófájl.</param>
        /// <returns>Igazat ad vissza ha a művelet sikeres volt.</returns>
        public bool AddVideo(VideoFile video)
        {
            if (Videos != null)
            {
                Videos.Add(video);
                return true;
            }
            return false;
        }
        #endregion

        #region Remove one item List type fields.
        /// <summary>
        /// Törli a megadott indexű képet.
        /// </summary>
        /// <param name="index">A törlendő kép indexe.</param>
        /// <returns>Igazat ad vissza ha a művelet sikeres volt.</returns>
        public bool RemoveImage(int index)
        {
            if (Pictures != null)
            {
                if (Pictures.Count > index && index >= 0)
                {
                    Pictures.RemoveAt(index);
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// Törli a megadott indexű hangot.
        /// </summary>
        /// <param name="index">A törlendő hang indexe.</param>
        /// <returns>Igazat ad vissza ha a művelet sikeres volt.</returns>
        public bool RemoveAudio(int index)
        {
            if (Audios != null)
            {
                if (Audios.Count > index && index >= 0)
                {
                    Audios.RemoveAt(index);
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// Törli a megadott indexű videót.
        /// </summary>
        /// <param name="index">A törlendő videó indexe.</param>
        /// <returns>Igazat ad vissza ha a művelet sikeres volt.</returns>
        public bool RemoveVideo(int index)
        {
            if (Videos != null)
            {
                if (Videos.Count > index && index >= 0)
                {
                    Videos.RemoveAt(index);
                    return true;
                }
            }
            return false;
        }
        #endregion

        #region Clear List type filelds.
        /// <summary>
        /// Törli az összes képet.
        /// </summary>
        /// <returns>Igazat ad vissza ha a művelet sikeres volt.</returns>
        public bool ClearImages()
        {
            if (Pictures != null)
            {
                Pictures.Clear();
                return true;
            }
            return false;
        }

        /// <summary>
        /// Törli az összes hangot.
        /// </summary>
        /// <returns>Igazat ad vissza ha a művelet sikeres volt.</returns>
        public bool ClearAudios()
        {
            if (Audios != null)
            {
                Audios.Clear();
                return true;
            }
            return false;
        }

        /// <summary>
        /// Törli az összes videót.
        /// </summary>
        /// <returns>Igazat ad vissza ha a művelet sikeres volt.</returns>
        public bool ClearVideos()
        {
            if (Videos != null)
            {
                Videos.Clear();
                return true;
            }
            return false;
        }
        #endregion

        #region Swap List type elements.
        /// <summary>
        /// Felcserél két Képet.
        /// </summary>
        /// <param name="from">Az egyik felcserélendő elem ahonna áthelyezzük.</param>
        /// <param name="to">A másik felcserélendő elem ahová az előzőt tesszük.</param>
        /// <returns>Igazat ad vissza ha a művelet sikeres volt.</returns>
        public bool SwapPictures(int from, int to)
        {
            if (Pictures != null)
            {
                if (Pictures.Count > from && from >= 0 && Pictures.Count > to && to >= 0)
                {
                    string Swap = Pictures[from];
                    Pictures[from] = Pictures[to];
                    Pictures[to] = Swap;
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// Felcserél két Audió fájlt.
        /// </summary>
        /// <param name="from">Az egyik felcserélendő elem ahonna áthelyezzük.</param>
        /// <param name="to">A másik felcserélendő elem ahová az előzőt tesszük.</param>
        /// <returns>Igazat ad vissza ha a művelet sikeres volt.</returns>
        public bool SwapAudios(int from, int to)
        {
            if (Audios != null)
            {
                if (Audios.Count > from && from >= 0 && Audios.Count > to && to >= 0)
                {
                    AudioFile Swap = Audios[from];
                    Audios[from] = Audios[to];
                    Audios[to] = Swap;
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// Felcserél két Videó fájlt.
        /// </summary>
        /// <param name="from">Az egyik felcserélendő elem ahonna áthelyezzük.</param>
        /// <param name="to">A másik felcserélendő elem ahová az előzőt tesszük.</param>
        /// <returns>Igazat ad vissza ha a művelet sikeres volt.</returns>
        public bool SwapVideos(int from, int to)
        {
            if (Videos != null)
            {
                if (Videos.Count > from && from >= 0 && Videos.Count > to && to >= 0)
                {
                    VideoFile Swap = Videos[from];
                    Videos[from] = Videos[to];
                    Videos[to] = Swap;
                    return true;
                }
            }
            return false;
        }
        #endregion

        #region Object class overwritten methods.
        /// <summary>
        /// Az aktuális objektummal összehasonlítja a paraméterkénbt megadott objektumot.
        /// </summary>
        /// <param name="obj">Az összehasonlítanó ojbektum.</param>
        /// <returns>Igazat ad vissza ha a két objektum megegyezik.</returns>
        public override bool Equals(object obj)
        {
            bool equals = true;
            Content other = obj as Content;

            if ((other != null)
                && (GetType() == other.GetType())
                && (GetHashCode() == other.GetHashCode()))
            {
                // ha count-ot nézel előtte ellenőrizd hogy nem e null az adattag!!
                if ((Title == other.Title)
                && (Details == other.Details)
                && (Pictures.Count == other.Pictures.Count)
                && (Audios.Count == other.Audios.Count)
                && (Videos.Count == other.Videos.Count))
                {

                    for (int i = 0; i < Pictures.Count; i++)
                    {
                        if (Pictures[i] != other.Pictures[i])
                        {
                            equals = false;
                            break;
                        }
                    }
                    // ha már kiderült hogy nem egyezik akkor ne menjünk végig a többin
                    for (int i = 0; i < this.Audios.Count; i++)
                    {
                        if (Audios[i] != other.Audios[i])
                        {
                            equals = false;
                            break;
                        }
                    }

                    for (int i = 0; i < this.Videos.Count; i++)
                    {
                        if (Videos[i] != other.Videos[i])
                        {
                            equals = false;
                            break;
                        }
                    }
                }

                else // ide akkor jövünk ha ... if feltétel
                {
                    equals = false;
                }
            }
            else // ide is
            {
                equals = false;
            }
            return equals;
        }

        /// <summary>
        /// Az objektum hash kódját adja vissza.
        /// </summary>
        /// <returns>Az objektum hash kódja intként.</returns>
        public override int GetHashCode()
        {
            int hash = 0;
            hash += Title.GetHashCode();// note: Title can't be null, so no checking is needed.
            hash += (Details == default(string)) ? 0 : Details.GetHashCode();

            if (Pictures != default(List<string>))
            {
                foreach (string picture in Pictures)
                {
                    if (picture != null)
                    {
                        hash += picture.GetHashCode();
                    }
                }
            }

            if (Audios != default(List<AudioFile>))
            {
                foreach (AudioFile audio in Audios)
                {
                    if (audio != null)
                    {
                        hash += audio.GetHashCode();
                    }
                }
            }

            if (Videos != default(List<VideoFile>))
            {
                foreach (VideoFile video in Videos)
                {
                    if (video != null)
                    {
                        hash += video.GetHashCode();
                    }
                }
            }
            return hash;
        }
        #endregion

        #region Class private field.
        /// <summary>
        /// A Content ikonja.
        /// </summary>
        private Image myIcon;

        /// <summary>
        /// A Content címe.
        /// </summary>
        private string myTitle;
        #endregion
    }
}